#include "func_spi_master.h"
#include "func_spi_slave.h"
#include "spi.h"
#include "usb_com.h"
#include "string.h"
#include "mem_malloc.h"

#define SPI_Master hspi1
extern SPI_HandleTypeDef SPI_Master;
static unsigned char *spiReadBuf;
static unsigned char *spiWriteBuf;
static unsigned char readLen;
static unsigned char writeReadLen = 0;
static unsigned long delay = 0;
#define SPI_CS_GPIO GPIOB          /* 连接到SDA数据线的GPIO */
#define SPI_CS_PIN GPIO_PIN_0     /* 连接到SDA数据线的GPIO */

#define SPI_DC_GPIO GPIOB          /* 连接到SDA数据线的GPIO */
#define SPI_DC_PIN GPIO_PIN_1     /* 连接到SDA数据线的GPIO */

#define BSP_SET_GPIO_1(gpio, pin)   gpio->BSRR = pin
#define BSP_SET_GPIO_0(gpio, pin)   gpio->BSRR = (uint32_t)(pin) << 16U

/// @brief usb设定串口参数
/// @param cmd
/// @param subCmd
/// @param data
void spi_master_set_param(unsigned char cmd, unsigned char subCmd, unsigned char *data)
{
    __HAL_SPI_DISABLE(&SPI_Master);
    HAL_SPI_DMAStop(&SPI_Master);
    HAL_SPI_DeInit(&SPI_Master);


    SPI_Master.Init.Mode = SPI_MODE_MASTER;
    SPI_Master.Init.Direction = SPI_DIRECTION_2LINES;
    SPI_Master.Init.DataSize = data[5] == SPI_DATA_SIZE_8 ? SPI_DATASIZE_8BIT : SPI_DATASIZE_16BIT;
    SPI_Master.Init.CLKPolarity = data[8] == SPI_CPOL_LOW ? SPI_POLARITY_LOW : SPI_POLARITY_HIGH;
    SPI_Master.Init.CLKPhase = data[9] == SPI_CPHA_1EDGE ? SPI_PHASE_1EDGE : SPI_PHASE_2EDGE;
    SPI_Master.Init.NSS = SPI_NSS_SOFT;
    if (&hspi1 == &SPI_Master)
    {
        switch (data[7])
        {
            case SPI_BAUD_18M:
                SPI_Master.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
                break;
            case SPI_BAUD_9M:
                SPI_Master.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
                break;
            case SPI_BAUD_4500K:
                SPI_Master.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
                break;
            case SPI_BAUD_2250K:
                SPI_Master.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
                break;
            case SPI_BAUD_1125K:
                SPI_Master.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
                break;
            case SPI_BAUD_562500:
                SPI_Master.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
                break;
            case SPI_BAUD_281250:
                SPI_Master.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
                break;

            default:
                break;
        }
    }
    else
    {
        switch (data[7])
        {
            case SPI_BAUD_18M:
                SPI_Master.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
                break;
            case SPI_BAUD_9M:
                SPI_Master.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
                break;
            case SPI_BAUD_4500K:
                SPI_Master.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
                break;
            case SPI_BAUD_2250K:
                SPI_Master.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
                break;
            case SPI_BAUD_1125K:
                SPI_Master.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
                break;
            case SPI_BAUD_562500:
                SPI_Master.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
                break;
            case SPI_BAUD_281250:
                SPI_Master.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
                break;

            default:
                break;
        }
    }



    SPI_Master.Init.FirstBit = data[6] == SPI_MSB ? SPI_FIRSTBIT_MSB : SPI_FIRSTBIT_LSB;
    SPI_Master.Init.TIMode = SPI_TIMODE_DISABLE;
    SPI_Master.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    SPI_Master.Init.CRCPolynomial = 10;
    SPI_Master.TxXferSize = 0;
    SPI_Master.TxXferCount = 0;
    SPI_Master.RxXferSize = 0;
    SPI_Master.RxXferCount = 0;
    SPI_Master.Instance->DR = 0;
    if (HAL_SPI_Init(&SPI_Master) != HAL_OK)
    {
        usb_cmd(COMM_SPI_MASTER, COMM_SUB_SPI_MASTER_SET_PARAM, (void *)COM_FAIL);
    }
    else
    {
        GPIO_InitTypeDef GPIO_InitStruct = {0};
        GPIO_InitStruct.Pin = GPIO_PIN_5 | GPIO_PIN_7;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
        GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Pin = GPIO_PIN_6;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
        usb_cmd(COMM_SPI_MASTER, COMM_SUB_SPI_MASTER_SET_PARAM, (void *)COM_OK);
    }
}

/// @brief usb接收到需要发送的数据
/// @param cmd
/// @param subCmd
/// @param data
void spi_master_send_data(unsigned char cmd, unsigned char subCmd, unsigned char *data)
{
    if (SPI_Master.Init.Mode == SPI_MODE_MASTER)
    {
        m_malloc(spiWriteBuf, data[2] - 7);
        if (spiWriteBuf == 0)
        {
            usb_cmd(COMM_SPI_MASTER, COMM_SUB_SPI_MASTER_WRITE, (void *)COM_MEM);
        }
        else
        {
            BSP_SET_GPIO_0(SPI_CS_GPIO, SPI_CS_PIN);
            if (data[5])
            {
                BSP_SET_GPIO_1(SPI_DC_GPIO, SPI_DC_PIN);
            }
            else
            {
                BSP_SET_GPIO_0(SPI_DC_GPIO, SPI_DC_PIN);
            }
            memcpy(spiWriteBuf, &data[6], data[2] - 7);
            if (HAL_SPI_Transmit_DMA(&SPI_Master, spiWriteBuf, data[2] - 7) == HAL_OK)
            {
                usb_cmd(COMM_SPI_MASTER, COMM_SUB_SPI_MASTER_WRITE, (void *)COM_OK);
                return;
            }
            else
            {
                m_free(spiWriteBuf);
                usb_cmd(COMM_SPI_MASTER, COMM_SUB_SPI_MASTER_WRITE, (void *)COM_FAIL);
            }
        }
    }
    else
    {
        usb_cmd(COMM_SPI_MASTER, COMM_SUB_SPI_MASTER_WRITE, (void *)COM_MODE);
    }
}

void spi_master_read_data(unsigned char cmd, unsigned char subCmd, unsigned char *data)
{
    if (SPI_Master.Init.Mode == SPI_MODE_MASTER)
    {
        readLen = data[5];

        writeReadLen = 0;
        m_malloc(spiReadBuf, BUFF_SIZE);
        if (spiReadBuf == 0)
        {
            usb_cmd(COMM_SPI_MASTER, COMM_SUB_SPI_MASTER_READ, (void *)COM_MEM);
        }
        else
        {
            BSP_SET_GPIO_0(SPI_CS_GPIO, SPI_CS_PIN);
            if (data[6])
            {
                BSP_SET_GPIO_1(SPI_DC_GPIO, SPI_DC_PIN);
            }
            else
            {
                BSP_SET_GPIO_0(SPI_DC_GPIO, SPI_DC_PIN);
            }
            SPI_Master.Instance->DR;// 先读取一次保证接收flag为空
            if (HAL_SPI_Receive_DMA(&SPI_Master, spiReadBuf, data[5]) != HAL_OK)
            {
                usb_cmd(COMM_SPI_MASTER, COMM_SUB_SPI_MASTER_READ, (void *)COM_FAIL);
                return;
            }
        }
    }
    else
    {
        usb_cmd(COMM_SPI_MASTER, COMM_SUB_SPI_MASTER_READ, (void *)COM_MODE);
    }
}

void spi_master_send_read_data(unsigned char cmd, unsigned char subCmd, unsigned char *data)
{
    if (SPI_Master.Init.Mode == SPI_MODE_MASTER)
    {
        writeReadLen = data[5];
        delay = (data[6] << 24) + (data[7] << 16) + (data[8] << 8) + data[9];

        m_malloc(spiWriteBuf, data[2] - 12);
        m_malloc(spiReadBuf, BUFF_SIZE);
        if (spiWriteBuf == 0 || spiReadBuf == 0)
        {
            if(spiWriteBuf)
            {
                m_free(spiWriteBuf);
            }
            if(spiReadBuf)
            {
                m_free(spiReadBuf);
            }
            usb_cmd(COMM_SPI_MASTER, COMM_SUB_SPI_MASTER_READ, (void *)COM_MEM);
        }
        else
        {
            BSP_SET_GPIO_0(SPI_CS_GPIO, SPI_CS_PIN);
            if (data[10])
            {
                BSP_SET_GPIO_1(SPI_DC_GPIO, SPI_DC_PIN);
            }
            else
            {
                BSP_SET_GPIO_0(SPI_DC_GPIO, SPI_DC_PIN);
            }
            memcpy(spiWriteBuf, &data[11], data[2] - 12);
            if (HAL_SPI_Transmit_DMA(&SPI_Master, spiWriteBuf, data[2] - 12) != HAL_OK)
            {
                usb_cmd(COMM_SPI_MASTER, COMM_SUB_SPI_MASTER_WRITE_READ, (void *)COM_FAIL);
                m_free(spiWriteBuf);
                m_free(spiReadBuf);
                return;
            }
        }
    }
    else
    {
        usb_cmd(COMM_SPI_MASTER, COMM_SUB_SPI_MASTER_WRITE_READ, (void *)COM_MODE);
    }

}

/// @brief usb上传接收到的数据
/// @param cmd
/// @param subCmd
/// @param param
void spi_master_rec_update(unsigned char cmd, unsigned char subCmd, void *param)
{
    unsigned char sendData[USB_PORT_SIZE] = {0};
    unsigned char len = readLen;
    sendData[0] = 0xaa;
    sendData[1] = 0x55;
    sendData[2] = len + 7;
    sendData[3] = COMM_SPI_MASTER;
    sendData[4] = COMM_SUB_SPI_MASTER_READ;
    sendData[5] = (unsigned char)param;
    if (spiReadBuf != 0)
    {
        memcpy(&sendData[6], spiReadBuf, len);
        my_free(spiReadBuf);
        spiReadBuf = 0;
    }
    sendData[len + 6] = chksum(sendData, len + 6);
    usb_send(sendData, len + 7);
}

/// @brief usb上传接收到的数据
/// @param cmd
/// @param subCmd
/// @param param
void spi_master_send_rec_update(unsigned char cmd, unsigned char subCmd, void *param)
{
    unsigned char sendData[USB_PORT_SIZE] = {0};
    unsigned char len = writeReadLen;
    sendData[0] = 0xaa;
    sendData[1] = 0x55;
    sendData[2] = len + 7;
    sendData[3] = COMM_SPI_MASTER;
    sendData[4] = COMM_SUB_SPI_MASTER_WRITE_READ;
    sendData[5] = (unsigned char)param;
    if (spiReadBuf != 0)
    {
        memcpy(&sendData[6], spiReadBuf, len);
        my_free(spiReadBuf);
        spiReadBuf = 0;
    }
    sendData[len + 6] = chksum(sendData, len + 6);
    usb_send(sendData, len + 7);
    writeReadLen = 0;
}

void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
    if (SPI_Master.Init.Mode == SPI_MODE_MASTER)
    {
        if (writeReadLen != 0)
        {
            if (delay != 0)
            {
                delay_us(delay);
            }
            SPI_Master.Instance->DR;// 先读取一次保证接收flag为空
            if (HAL_SPI_Receive_DMA(&SPI_Master, spiReadBuf, writeReadLen) != HAL_OK)
            {
                m_free(spiReadBuf);
                usb_cmd(COMM_SPI_MASTER, COMM_SUB_SPI_MASTER_WRITE_READ, (void *)COM_FAIL);
                return;
            }

        }
        else
        {
            BSP_SET_GPIO_1(SPI_CS_GPIO, SPI_CS_PIN);
            usb_cmd(COMM_SPI_MASTER, COMM_SUB_SPI_MASTER_WRITE, (void *)COM_OK);
        }
    }
    else
    {
        slave_txc_cb();
    }
    m_free(spiWriteBuf);
}

void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
    if (SPI_Master.Init.Mode == SPI_MODE_MASTER)
    {
        BSP_SET_GPIO_1(SPI_CS_GPIO, SPI_CS_PIN);
        if (writeReadLen != 0)
        {
            usb_cmd(COMM_SPI_MASTER, COMM_SUB_SPI_MASTER_WRITE_READ, (void *)COM_OK);
        }
        else
        {
            usb_cmd(COMM_SPI_MASTER, COMM_SUB_SPI_MASTER_READ, (void *)COM_OK);
        }
    }
    else
    {
        slave_rxc_cb();
    }
}
